﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace Avanzis.QueryBuilder.Fluent
{
    ///<summary>
    ///</summary>
    public class Filters : IEnumerable<SearchPredicate>
    {
        private readonly SearchFiltersCollection filters;

        ///<summary>
        ///</summary>
        public Filters()
        {
            filters = new SearchFiltersCollection();
        }

        ///<summary>
        ///</summary>
        public Filters(string initialFilter) : this()
        {
            filters.Add(initialFilter);
        }

        ///<summary>
        ///</summary>
        ///<param name="leftExpression"></param>
        ///<param name="compareOperator"></param>
        ///<param name="rightExpression"></param>
        ///<returns></returns>
        public Filters And(object leftExpression, SqlOperator compareOperator,  object rightExpression)
        {
            filters.Add(leftExpression, compareOperator, rightExpression);
            return this;
        }

        ///<summary>
        ///</summary>
        ///<param name="leftExpression"></param>
        ///<param name="compareOperator"></param>
        ///<param name="rightExpression"></param>
        ///<typeparam name="T"></typeparam>
        ///<returns></returns>
        public Filters And<T>(Expression<Func<T, object>> leftExpression, SqlOperator compareOperator, object rightExpression)
        {
            string stringExpression = FluentHelper.ParseProperty(leftExpression);
            return this.And(stringExpression, compareOperator, rightExpression);
        }

        ///<summary>
        ///</summary>
        ///<param name="leftExpression"></param>
        ///<param name="rightExpression"></param>
        ///<typeparam name="T"></typeparam>
        ///<returns></returns>
        public Filters And<T>(Expression<Func<T, object>> leftExpression, object rightExpression)
        {
            return And<T>(leftExpression, SqlOperator.Equals, rightExpression);
        }

        ///<summary>
        ///</summary>
        ///<param name="expression"></param>
        ///<returns></returns>
        public Filters And(string expression)
        {
            filters.Add(expression);
            return this;
        }


        ///<summary>
        ///</summary>
        ///<param name="expression"></param>
        ///<returns></returns>
        public Filters Or(string expression )
        {
            filters.Add(FilterUnion.Or, expression);
            return this;
        }

        ///<summary>
        ///</summary>
        ///<param name="expression"></param>
        ///<returns></returns>
        public Filters Or(Filters expression)
        {
            filters.Add(FilterUnion.Or, expression.ToString());
            return this;
        }

        ///<summary>
        ///</summary>
        ///<param name="leftExpression"></param>
        ///<param name="compareOperator"></param>
        ///<param name="rightExpression"></param>
        ///<returns></returns>
        public Filters Or(object leftExpression, SqlOperator compareOperator, object rightExpression)
        {
            filters.Add(FilterUnion.Or, leftExpression, compareOperator, rightExpression);
            return this;
        }

        ///<summary>
        ///</summary>
        ///<param name="leftExpression"></param>
        ///<param name="compareOperator"></param>
        ///<param name="rightExpression"></param>
        ///<typeparam name="T"></typeparam>
        ///<returns></returns>
        public Filters Or<T>(Expression<Func<T, object>> leftExpression, SqlOperator compareOperator, object rightExpression)
        {
            string stringExpression = FluentHelper.ParseProperty(leftExpression);
            return this.Or(stringExpression, compareOperator, rightExpression);
        }

        ///<summary>
        ///</summary>
        ///<param name="leftExpression"></param>
        ///<param name="rightExpression"></param>
        ///<typeparam name="T"></typeparam>
        ///<returns></returns>
        public Filters Or<T>(Expression<Func<T, object>> leftExpression, object rightExpression)
        {
            return Or(leftExpression, SqlOperator.Equals, rightExpression);
        }


        public IEnumerator<SearchPredicate> GetEnumerator()
        {
            return filters.GetEnumerator();
        }

        public override string ToString()
        {
            return filters.ToString();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}